package main

import "C"
import (
	"fmt"
	"gitee.com/zhaojh329/go-btstack"
	"os"
)

var connectionHandle uint16
var serviceUuid uint16 = 0x1000
var service *btstack.GattClientServiceType
var characteristicUuid uint16 = 0x1001
var characteristic *btstack.GattClientCharacteristicType
var Listened bool

func main() {
	btstack.StdinSetup(stdinProcess)

	btstack.HciDumpOpen("hci_dump.pklg", btstack.HciDumpPacketlogger)

	btstack.MemoryInit()

	btstack.RunLoopInit(btstack.RunLoopWindowsGetInstance())

	btstack.HciInit(btstack.HciTransportUsbInstance(), nil)

	btstack.L2capInit()

	btstack.SmInit()

	btstack.SmSetIoCapabilities(btstack.IoCapabilityNoInputNoOutput)

	btstack.GattClientInit()

	btstack.HciSetEventHandler(packetHandler)

	btstack.GapRandomAddressSetMode(btstack.GapRandomAddressNonResolvable)

	btstack.HciPowerControl(btstack.HciPowerOn)

	btstack.RunLoopExecute()
}

func packetHandler(packet interface{}) {
	switch packet := packet.(type) {
	case *btstack.EventPoweronFailedPacket:
		fmt.Println("Power on failed")
		btstack.HciClose()
		os.Exit(1)
	case *btstack.EventStatePacket:
		if packet.State() == btstack.HciStateWorking {
			baddr := btstack.GapLocalBdAddr()
			fmt.Println("BTstack activated, get started: ", baddr)
			btstack.GapSetScanParameters(1, 0x30, 0x30)
			btstack.GapStartScan()
		}
	case *btstack.EventAdvertisingReportPacket:
		fmt.Println(packet.Type(), packet.AddressType(), packet.Address(), packet.Rssi(), packet.Name(), packet.Flags())

		if packet.Name() == "bts" {
			btstack.GapStopScan()
			btstack.GapConnect(packet.Address(), packet.AddressType())
		}
	case *btstack.EventLeConnectionCompletePacket:
		connectionHandle = packet.Handle()
		fmt.Printf("New connection: Role: %d, Handle: 0x%04x, Interval: %.2f, Latency: %d\n",
			packet.Role(), connectionHandle, packet.Interval(), packet.Latency())
		btstack.DiscoverPrimaryServicesByUUID16(connectionHandle, serviceUuid)
	case *btstack.EventDisconnectionCompletePacket:
		fmt.Printf("Disconnect Handle: 0x%04x, Status: 0x%02x, Reason: 0x%02x\n",
			packet.Handle(), packet.Status(), packet.Reason())
	case *btstack.EventLeServiceQueryResultPacket:
		service = packet.Service()
		fmt.Printf("Service uuid16: 0x%04x\n", service.UUID16())
	case *btstack.EventCharacteristicQueryResult:
		characteristic = packet.Characteristic()
		fmt.Printf("Characteristic uuid16: 0x%04x\n", characteristic.UUID16())
	case *btstack.EventQueryCompletePacket:
		status := packet.AttStatus()	// ATT_ERROR_xxx

		if characteristic == nil {
			if status != 0 {
				fmt.Printf("SERVICE_QUERY_RESULT - Error status 0x%02x\n", status)
				return
			}

			btstack.DiscoverCharacteristicsForServiceByUUID16(connectionHandle, service, characteristicUuid)
			return
		} else if !Listened {
			if status != 0 {
				fmt.Printf("CHARACTERISTIC_QUERY_RESULT - Error status 0x%02x\n", status)
				return
			}

			Listened = true
			btstack.ListenForCharacteristicValueUpdates(connectionHandle, characteristic, func(valueHandle uint16, value []byte) {
				fmt.Println("Value update:", valueHandle, value)
				btstack.WriteValueOfCharacteristicWithoutResponse(connectionHandle, characteristic.ValueHandle(), []byte{0x12, 0x33})
			})
		}
	}
}

func stdinProcess(cmd byte)  {
	if cmd == 'q' {
		btstack.HciClose()
		os.Exit(0)
	}
}